package com.linkai.JUC._01_syn;

import com.linkai.源码.ArrayList;

/**
 * @Description: synchronized 底层实现原理
 *
 *               参考：《深入理解Java虚拟机》
 *                  https://www.cnblogs.com/jimoer/p/13664252.html
 *                  https://blog.csdn.net/weixin_38481963/article/details/88384493
 *              编译成字节码文件之后，执行反编译查看内容：
 *              反编译文件的第103行和第111行，第81行
 *              synchronized关键字在经过Javac编译之后，会在同步块的前后形成monitorenter和monitorexit两个字节码指令。
 *                  在执行monitorenter指令的时候，首先要去尝试获取对象的锁（获取对象锁的过程，其实是获取monitor对象的所有权的过程）。
 *                  如果这个对象没被锁定，或者当前线程已经持有了那个对象的锁，就把锁的计数器的值增加一。
 *                  而在执行monitorexit指令时会将锁计数器减一。一旦计数器的值为零，锁随即就被释放了。
 *                  如果获取对象锁失败，那当前线程就应当被阻塞等待，直到请求锁定的对象被持有它的线程释放为止。
*               同步方法，反编译后得到ACC_SYNCHRONIZED 标志，对于同步代码块反编译后得到monitorenter和monitorexit指令。
*
 * @Author: 林凯
 * @Date: 2021/10/28 20:27
 */
public class SynchronizedTest {

    public static int number = 0;

    // synchronized 使用在静态方法上
    public static synchronized void test1() {
        System.out.println("test1");
    }

    // 就很懵？锁不住？
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                SynchronizedTest synchronizedTest = new SynchronizedTest();
                synchronizedTest.addNum();
            }).start();
        }
        while (Thread.activeCount() > 2) {

        }
        System.out.println(number);
    }

    private void addNum() {
        number++;
    }

    public static void testSyn() {
        ArrayList<Integer> arrayList = new ArrayList<>();
        synchronized (arrayList) {
            for (int i = 0; i < 10000; i++) {
                int temp = i;
                new Thread(()->{
                    arrayList.add(temp);
                }).start();
            }
        }
        while (Thread.activeCount() > 2){

        }
        System.out.println(arrayList.size());;
    }
}
